package engine

import (
	"strings"
)

type ConcurrentEngine struct {
	Scheduler        Scheduler
	WorkerCount      int
	ItemChan         chan Item
	RequestProcessor Processor
}

type Processor func (Request) (ParseResult,error)

type Scheduler interface {
	Sumbit(request Request)
	WorkerChan() chan Request
	ReadyNotifier
	Run()
}

type ReadyNotifier interface {
	WorkerReady(chan Request)

}

func (e *ConcurrentEngine) Run(seeds ...Request) {

	out := make(chan ParseResult)
	e.Scheduler.Run()
	for i := 0; i < e.WorkerCount; i++ {
		e.createWorker(e.Scheduler.WorkerChan(),out, e.Scheduler)
	}
	for _, r := range seeds {
		e.Scheduler.Sumbit(r)
	}
	for {
		result := <-out
		for _, item := range result.Items {
			go func() {e.ItemChan <- item}()
		}
		for _, request := range result.Requests {
			if isDuplicate(request.Url) {
				continue
			}
			e.Scheduler.Sumbit(request)
		}

	}
}
var visitedUrls = make(map[string]bool)

func isDuplicate(url string) bool {
	if visitedUrls[url] {
		return true
	}
	visitedUrls[url] = true
	return false
}
func (e *ConcurrentEngine)createWorker(in chan Request,
	out chan ParseResult, ready ReadyNotifier) {
	go func() {
		for {
			//tell schelduler i'm ready
			ready.WorkerReady(in)
			request := <- in
			//parserResult, error := Worker(request)
			parserResult, error := e.RequestProcessor(request)//CallRpc
			if error != nil {
				if strings.Contains(error.Error(),"wrong bad body : 403") {
					go func() {in <- request}()
				}
				continue
			}
			out <- parserResult
		}
	}()
}
